//
//  SSDKHttpUtil.m
//  SuperSDK
//
//  Created by wyht－ios－dev on 15/10/6.
//  Copyright © 2015年 WYHT. All rights reserved.
//

#import "SSDKHttpUtil.h"
#import "SSDKBaseReqData.h"
#import "SSDKBaseResData.h"
#import "SuperSDKInst.h"
#import "SSDKLoginData.h"
#import "SSDKDataKeys.h"
#import "SSDKEnum.h"
#import "SSDKLoginData.h"
#import "SSDKDataHelper.h"
#import "SSDKActivityInfo.h"
#import "SSDKUIManager.h"
#import "SuperSDKPluginTools/SSDKPluginToast.h"
#import "SuperSDKPluginTools/SSDKPluginReachability.h"
#import "SuperSDKPluginTools/SSDKPluginJsonUtil.h"
#import "SUperSDKPluginTools/SSDKPluginEncryptUtil.h"

#pragma mark - SSDKHttpUtil

@implementation SSDKHttpUtil
{
    NSTimer *timer;    
    NSMutableArray *requestRecord;
    NSMutableArray *serverErrorRequestRecord;
}

static SSDKHttpUtil *instance = nil;

static int const TIME_OUT = 8;

static NSString *urlKey = @"urlRecord";
static NSString *recordKey = @"recordRecord";
static NSString *gotInfoKey = @"gotInfoRecord";

+(instancetype) getInstance
{
    if(instance==nil)
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
        });
    }
    return instance;
}

-(void) timerFinish
{
    if ([SSDKHttpUtil isNetworkReachable]) {
        if (timer != nil) {
            [timer invalidate];
            timer = nil;
            int count = [requestRecord count];
            for (int i=0;i<count;i++) {
                NSMutableDictionary *one = [requestRecord objectAtIndex:i];
                [SSDKHttpUtil postWithUrl : [one objectForKey:urlKey]
                                     data : [one objectForKey:recordKey]
                             httpDelegate : [one objectForKey:gotInfoKey]];
            }
            requestRecord = nil;
        }
    } else {
        [[[SSDKPluginToast makeText:@"未检测到网络"] setDuration:2000] show];
    }
}

+(BOOL) isNetworkReachable
{
    BOOL isReachable = NO;
    SSDKPluginReachability *reachability = [SSDKPluginReachability reachabilityWithHostName:@"blrssdk.sail2world.com"];
    switch ([reachability currentReachabilityStatus]) {
        case NotReachable:{
            isReachable = NO;
        }
            break;
            //        case ReachableViaWWAN:{
            //            isReachable = YES;
            //        }
            //            break;
            //        case ReachableViaWiFi:{
            //            isReachable = YES;
            //        }
            //            break;
        default:
            isReachable = YES;
            break;
    }
    return isReachable;
}

//支持断网时多次请求
- (void) addDataToRequestRecord:(NSMutableDictionary *)requestItem {
    if (requestRecord == nil) {
        requestRecord = [[NSMutableArray alloc] init];
    }
    [requestRecord addObject:requestItem];
}

- (void) initTimer {
    if (timer == nil) {
        timer=[NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:@selector(timerFinish) userInfo:nil repeats:YES];
    }
}

+ (void) postWithUrl : (NSString *)url
                data : (SSDKBaseReqData *)data
        httpDelegate : (void (^)(SSDKBaseResData* resData))gotInfo {
    
    if (![SSDKHttpUtil isNetworkReachable]) {
        [[[SSDKPluginToast makeText:@"未检测到网络"] setDuration:2000] show];

        NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
        [requestItem setObject:url forKey:urlKey];
        [requestItem setObject:data forKey:recordKey];
        [requestItem setObject:gotInfo forKey:gotInfoKey];
        [[SSDKHttpUtil getInstance] addDataToRequestRecord:requestItem];
        [[SSDKHttpUtil getInstance] initTimer];
        return;
    }
    
    NSString *reqStr = [[NSString alloc] initWithFormat:@"%@=%@", JSON_DATA, [self encodeString:data.toJson]];
    NSData *postData = [reqStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
    
    NSURL *nsUrl = [[NSURL alloc] initWithString:url];
    
    NSMutableURLRequest *request = [NSMutableURLRequest
                                    requestWithURL : nsUrl
                                    cachePolicy:NSURLRequestReloadIgnoringCacheData
                                    timeoutInterval:TIME_OUT];
    request.HTTPMethod = @"POST";
    
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    //处理超时连接
    [request setValue:@"close" forHTTPHeaderField:@"Connection"];
    
    request.HTTPBody = postData;
    
    NSOperationQueue *queue = [NSOperationQueue new];
    
    [SSDKUIManager showLoadingUI];
    
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *jsonData, NSError *error) {
        
        [SSDKUIManager dismissLoadingUI];
        
        SSDKBaseResData *resData = [[SSDKBaseResData alloc] init];
        
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
        NSInteger status = [httpResponse statusCode];
        if (200 == status) {
            NSString *dataStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
            NSMutableDictionary *resDic = [SSDKPluginJsonUtil toObjectWithJson:dataStr];
            resData = [[SSDKBaseResData alloc] initWithDictionary:resDic];
            //删除保存的请求记录
            [[SSDKHttpUtil getInstance] findRequestRecord:url data:data httpDelegate:gotInfo];
            //接入applePay不能使用UI线程回调
            gotInfo(resData);
        } else {
            [resData fail];
            [resData setError : @"NETWORK_TIME_OUT"
                     withCode : NETWORK_TIME_OUT
                      withMsg : error.localizedDescription];
            //接入applePay不能使用UI线程回调
            if([[SSDKHttpUtil getInstance] findRequestRecord:url data:data httpDelegate:gotInfo]) {
                [SSDKHttpUtil postWithUrl:url data:data httpDelegate:gotInfo];
            } else {
                gotInfo(resData);
            }
        }
    }];
}

//支持服务器返回异常时二次请求
-(void) addRequestRecord:(NSMutableDictionary *)requestItem {
    if (serverErrorRequestRecord == nil) {
        serverErrorRequestRecord = [[NSMutableArray alloc] init];
    }
    [serverErrorRequestRecord addObject:requestItem];
}

//比对是否有请求记录
-(BOOL) findRequestRecord:(NSString *)url
                    data : (SSDKBaseReqData *)data
            httpDelegate : (void (^)(SSDKBaseResData* resData))gotInfo {
    if(serverErrorRequestRecord==nil)
        return false;
    int count = serverErrorRequestRecord.count;
    for (int i=0;i<count;i++) {
        NSMutableDictionary *one = [serverErrorRequestRecord objectAtIndex:i];
        //gotInfo不做判断，NSDictionary判断不到
        if([[one objectForKey:urlKey] isEqualToString:url] &&
           [[one objectForKey:recordKey] isEqual:data]) {
            [serverErrorRequestRecord removeObjectAtIndex:i];
            return true;
        }
    }
    return false;
}

+(NSString*) encodeString:(NSString*)unencodedString {
    NSString *encodedString = (NSString *)
    CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                              (CFStringRef)unencodedString,
                                                              NULL,
                                                              (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                              kCFStringEncodingUTF8));
    
    return encodedString;
}

@end



# pragma mark - SSDKConfigUtil

@implementation SSDKConfigUtil

static NSString *SDK_CONFIG_QUERY_PATH = @"/supersdk-web/app/query/queryConfig";

+ (void) postWithHttpDelegate:(void (^)(SSDKBaseResData* resData))gotInfo {
    
    SSDKBaseReqData *reqData = [self generateReqData];
    
    NSString *url = [[SuperSDKInst getInstance] sUrl];
    url = [url stringByAppendingString:SDK_CONFIG_QUERY_PATH];
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:reqData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url data:reqData httpDelegate:gotInfo];
    
}

+ (SSDKBaseReqData *) generateReqData {
    SSDKBaseReqData *reqData = [[SSDKBaseReqData alloc] init];
    
    reqData.appId = [[SuperSDKInst getInstance] appId];
    reqData.channelId = [[SuperSDKInst getInstance] channelId];
    reqData.sdkId = [[SuperSDKInst getInstance] sdkId];
    
    NSString *appSecret = [[SuperSDKInst getInstance] appSecret];
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:reqData.data useSignKey:appSecret];
    reqData.sign = sign;
    
    return reqData;
}

@end


# pragma mark - SSDKSwitchConfigUtil

@implementation SSDKSwitchConfigUtil

static NSString *SDK_SWITCH_QUERY_PATH = @"/supersdk-web/app/query/querySwitch";

+ (void) postWithHttpDelegate:(void (^)(SSDKBaseResData* resData))gotInfo {
    
    SSDKBaseReqData *reqData = [[SSDKBaseReqData alloc] init];
    reqData.appId = [[SuperSDKInst getInstance] appId];
    reqData.channelId = [[SuperSDKInst getInstance] channelId];
    NSString *appSecret = [[SuperSDKInst getInstance] appSecret];
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:reqData.data useSignKey:appSecret];
    reqData.sign = sign;
    
    NSString *url = [[SuperSDKInst getInstance] sUrl];
    url = [url stringByAppendingString:SDK_SWITCH_QUERY_PATH];
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:reqData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url data:reqData httpDelegate:gotInfo];
    
}

@end


#pragma mark - SSDKPayInfoUtil

@implementation SSDKPayInfoUtil

static NSString *CREATE_ORDER_REQUEST_PATH = @"/supersdk-web/app/pay/createOrder";

+ (void) postWithData:(SSDKPaymentData *)data
        httpDelegate:(void (^)(SSDKBaseResData* resData))gotInfo {
    [self postWithData:data extra:nil httpDelegate:gotInfo];
}

+ (void) postWithData:(SSDKPaymentData *)data
               extra:(NSMutableDictionary *)extra
        httpDelegate:(void (^)(SSDKBaseResData* resData))gotInfo {
    
    SSDKPaymentData *pData = [self finishData:data withExtra:extra];
    
    NSString *url = [[SuperSDKInst getInstance] sUrl];
    url = [url stringByAppendingString:CREATE_ORDER_REQUEST_PATH];
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:pData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url data:pData httpDelegate:gotInfo];
    
}

+ (SSDKPaymentData *) finishData : (SSDKPaymentData *) data
          withExtra : (NSMutableDictionary *) extra {
    data.appId = [[SuperSDKInst getInstance] appId];
    data.channelId = [[SuperSDKInst getInstance] channelId];
    
    NSString* sign = [SSDKPluginEncryptUtil generateSignWithDictionary:data.data
                                                      useSignKey:[[SuperSDKInst getInstance] appSecret]];
    data.sign = sign;
    
    if (extra) {
        data.extra = extra;
    }
    else {
        data.extra = [[NSMutableDictionary alloc] init];
    }
    
    return data;
}

@end


#pragma mark - SSDKUserInfoUtil

@implementation SSDKUserInfoUtil

static NSString *SDK_LOGIN_CHECK_PATH = @"/supersdk-web/app/user/loginIn";

+ (void) postWithSdkUid : (NSString *) sdkUid
        accessToken : (NSString *) aToken
       refreshToken : (NSString *) rToken
       httpDelegate : (void (^)(SSDKBaseResData* resData))gotInfo {
    
    [self postWithSdkUid:sdkUid
             accessToken:aToken
            refreshToken:rToken
                   extra:nil
            httpDelegate:gotInfo];
}

+(void) postWithDataPart:(NSMutableDictionary *)dataPart extra:(NSMutableDictionary *)extra httpDelegate:(void (^)(SSDKBaseResData *))gotInfo
{
    SSDKLoginData *reqData = [[SSDKLoginData alloc] init];
    reqData.appId = [[SuperSDKInst getInstance] appId];
    reqData.channelId = [[SuperSDKInst getInstance] channelId];
    [reqData.data addEntriesFromDictionary:dataPart];
    
    if (extra) {
        reqData.extra = extra;
    }
    else {
        reqData.extra = [[NSMutableDictionary alloc] init];
    }
    
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:reqData.data useSignKey:[[SuperSDKInst getInstance] appSecret]];
    reqData.sign = sign;
    
    //装配lgoin的透传参数
    reqData.appData = [SSDKDataHelper loginAppData];
    
    NSString *url = [[SuperSDKInst getInstance] loginUrl];
    if(url==nil || url.length==0) {
        url = [[[SuperSDKInst getInstance] sUrl] stringByAppendingString:SDK_LOGIN_CHECK_PATH];
    }
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:reqData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url
                         data:reqData
                 httpDelegate:gotInfo];
    
}

+ (void) postWithSdkUid : (NSString *) sdkUid
            accessToken : (NSString *) aToken
           refreshToken : (NSString *) rToken
                  extra : (NSMutableDictionary *) extra
           httpDelegate : (void (^)(SSDKBaseResData* resData))gotInfo {
    
    SSDKLoginData *loginData = [self generateReqDataWithSdkUid:sdkUid
                                                   accessToken:aToken
                                                  refreshToken:rToken
                                                         extra:extra];
    
    //装配lgoin的透传参数
    loginData.appData = [SSDKDataHelper loginAppData];
    
    NSString *url = [[SuperSDKInst getInstance] loginUrl];
    if(url==nil || url.length==0) {
        url = [[[SuperSDKInst getInstance] sUrl] stringByAppendingString:SDK_LOGIN_CHECK_PATH];
    }
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:loginData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url
                         data:loginData
                 httpDelegate:gotInfo];
}

+ (SSDKLoginData *) generateReqDataWithSdkUid : (NSString *) sdkUid
                                  accessToken : (NSString *) aToken
                                 refreshToken : (NSString *) rToken
                                        extra : (NSMutableDictionary *) extra {
    SSDKLoginData *reqData = [[SSDKLoginData alloc] init];
    
    reqData.sdkUid = sdkUid;
    reqData.accessToken = aToken;
    reqData.refreshToken = rToken;
    
    reqData.appId = [[SuperSDKInst getInstance] appId];
    reqData.channelId = [[SuperSDKInst getInstance] channelId];
    
    if (extra) {
        reqData.extra = extra;
    }
    else {
        reqData.extra = [[NSMutableDictionary alloc] init];
    }
    
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:reqData.data useSignKey:[[SuperSDKInst getInstance] appSecret]];
    reqData.sign = sign;
    
    return reqData;
    
}

@end


@implementation SSDKCheckPayStatesUtil

static NSString *SDK_CHECK_ORDER_PATH = @"/supersdk-web/app/pay/checkOrder";

+(void) postWithSSDKUid:(NSString *)superSDKUid orderID:(NSString *)orderID extraData:(NSMutableDictionary *) extraData httpDelegate:(void (^)(SSDKBaseResData *))gotInfo
{
    NSString *url = [[SuperSDKInst getInstance] sUrl];
    url = [url stringByAppendingString:SDK_CHECK_ORDER_PATH];
    
    SSDKCheckOrderInfo *orderData = [[SSDKCheckOrderInfo alloc] init];
    
    orderData.appId = [[SuperSDKInst getInstance] appId];
    orderData.channelId = [[SuperSDKInst getInstance] channelId];
    
    if(superSDKUid!=nil)
        [orderData setSuperSDKUid:superSDKUid];
    [orderData setSSDKOrderID:orderID];
    
    if(extraData!=nil)
    {
        [orderData setExtra:extraData];
    }
    
    NSString *appSecret = [[SuperSDKInst getInstance] appSecret];
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:orderData.data useSignKey:appSecret];
    orderData.sign = sign;
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:orderData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url
                         data:orderData
                 httpDelegate:gotInfo];
}

+(void) postWithSSDKUid:(NSString *)superSDKUid orderID:(NSString *)orderID httpDelegate:(void (^)(SSDKBaseResData *))gotInfo
{
    [self postWithSSDKUid:superSDKUid orderID:orderID extraData:nil httpDelegate:gotInfo];
}

@end

@implementation SSDKActivityUtil

static NSString *SDK_ACTIVITY_PATH = @"/supersdk-web/app/activity/sdkActivity";

+(void) postWithSSDKUid:(NSString *)superSDKUid activityType:(NSString *)activityType otherData:(NSMutableDictionary *)otherData httpDelegate:(void (^)(SSDKBaseResData* resData))gotInfo {
    NSString *url = [[SuperSDKInst getInstance] sUrl];
    url = [url stringByAppendingString:SDK_ACTIVITY_PATH];
    
    SSDKActivityInfo *activityData = [[SSDKActivityInfo alloc] init];
    
    activityData.appId = [[SuperSDKInst getInstance] appId];
    activityData.channelId = [[SuperSDKInst getInstance] channelId];
    [activityData setSuperSDKUid:superSDKUid];
    [activityData setActivityType:activityType];
    if(otherData!=nil)
        [activityData setOtherData:otherData];
    
    NSString *appSecret = [[SuperSDKInst getInstance] appSecret];
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:activityData.data useSignKey:appSecret];
    activityData.sign = sign;
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:activityData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url
                         data:activityData
                 httpDelegate:gotInfo];
}

@end



@implementation SSDKTicketUtil

static NSString *SDK_TICKET_PATH = @"/supersdk-web/app/ticket/checkTicket";

+ (void) postWithTicket : (NSString *) ticket
           httpDelegate : (void (^)(SSDKBaseResData* resData))gotInfo {
    NSString *url = [[SuperSDKInst getInstance] sUrl];
    url = [url stringByAppendingString:SDK_TICKET_PATH];
    
    SSDKBaseReqData *paramData = [[SSDKBaseReqData alloc] init];
    
    paramData.appId = [[SuperSDKInst getInstance] appId];
    paramData.channelId = [[SuperSDKInst getInstance] channelId];
    [paramData setDataValue:[[SuperSDKInst getInstance] uid] forKey:@"supersdk_uid"];
    [paramData setDataValue:[[SuperSDKInst getInstance] token] forKey:@"supersdk_token"];
    [paramData setDataValue:ticket forKey:@"ticket"];
    
    NSString *appSecret = [[SuperSDKInst getInstance] appSecret];
    NSString *sign = [SSDKPluginEncryptUtil generateSignWithDictionary:paramData.data useSignKey:appSecret];
    paramData.sign = sign;
    
    NSMutableDictionary *requestItem = [[NSMutableDictionary alloc] init];
    [requestItem setObject:url forKey:urlKey];
    [requestItem setObject:paramData forKey:recordKey];
    [requestItem setObject:gotInfo forKey:gotInfoKey];
    [[SSDKHttpUtil getInstance] addRequestRecord:requestItem];
    [SSDKHttpUtil postWithUrl:url
                         data:paramData
                 httpDelegate:gotInfo];
}

@end

